# -*- coding: utf-8 -*-
"""
异步任务处理工具
使用Celery处理耗时操作，提高系统响应速度
"""

import os
from celery import Celery
from flask import current_app
from typing import Dict, Any


def make_celery(app):
    """创建Celery实例"""
    celery = Celery(
        app.import_name,
        backend=app.config.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/1'),
        broker=app.config.get('CELERY_BROKER_URL', 'redis://localhost:6379/0')
    )
    
    class ContextTask(celery.Task):
        def __call__(self, *args, **kwargs):
            with app.app_context():
                return self.run(*args, **kwargs)
    
    celery.Task = ContextTask
    return celery


# 创建Celery实例
celery_app = make_celery(None)


@celery_app.task(bind=True)
def send_notification(self, user_id: int, message: str, notification_type: str = 'system'):
    """
    发送通知任务
    :param user_id: 用户ID
    :param message: 消息内容
    :param notification_type: 通知类型
    """
    try:
        # 这里可以集成推送服务，如微信模板消息、短信等
        current_app.logger.info(f"发送通知给用户 {user_id}: {message}")
        
        # 模拟发送过程
        import time
        time.sleep(1)
        
        return {
            'status': 'success',
            'user_id': user_id,
            'message': message,
            'type': notification_type
        }
    except Exception as e:
        current_app.logger.error(f"发送通知失败: {e}")
        raise self.retry(countdown=60, max_retries=3)


@celery_app.task(bind=True)
def process_payment_async(self, order_id: int, payment_data: Dict[str, Any]):
    """
    异步处理支付
    :param order_id: 订单ID
    :param payment_data: 支付数据
    """
    try:
        from app.models.order import Order
        from app.models.payment import Payment
        
        order = Order.query.get(order_id)
        if not order:
            raise ValueError(f"订单不存在: {order_id}")
        
        # 处理支付逻辑
        payment = Payment(
            order_id=order_id,
            amount=payment_data.get('amount'),
            payment_method=payment_data.get('method'),
            status='processing'
        )
        
        # 这里可以调用第三方支付API
        # 模拟支付处理
        import time
        time.sleep(2)
        
        payment.status = 'success'
        order.status = 'paid'
        
        from app import db
        db.session.add(payment)
        db.session.commit()
        
        return {
            'status': 'success',
            'order_id': order_id,
            'payment_id': payment.id
        }
    except Exception as e:
        current_app.logger.error(f"支付处理失败: {e}")
        raise self.retry(countdown=120, max_retries=2)


@celery_app.task(bind=True)
def generate_report_async(self, report_type: str, filters: Dict[str, Any]):
    """
    异步生成报表
    :param report_type: 报表类型
    :param filters: 过滤条件
    """
    try:
        # 根据报表类型生成不同的报表
        if report_type == 'venue_usage':
            data = generate_venue_usage_report(filters)
        elif report_type == 'user_activity':
            data = generate_user_activity_report(filters)
        elif report_type == 'revenue':
            data = generate_revenue_report(filters)
        else:
            raise ValueError(f"不支持的报表类型: {report_type}")
        
        # 保存报表到文件或数据库
        report_file = save_report_to_file(report_type, data)
        
        return {
            'status': 'success',
            'report_type': report_type,
            'file_path': report_file,
            'data_count': len(data) if isinstance(data, list) else 1
        }
    except Exception as e:
        current_app.logger.error(f"生成报表失败: {e}")
        raise self.retry(countdown=300, max_retries=1)


@celery_app.task(bind=True)
def cleanup_expired_data(self):
    """清理过期数据任务"""
    try:
        from datetime import datetime, timedelta
        from app.models.order import Order
        from app.models.payment import Payment
        
        # 清理30天前的未支付订单
        expired_date = datetime.now() - timedelta(days=30)
        expired_orders = Order.query.filter(
            Order.status == 'pending',
            Order.created_at < expired_date
        ).all()
        
        for order in expired_orders:
            order.status = 'cancelled'
        
        # 清理过期的支付记录
        expired_payments = Payment.query.filter(
            Payment.status == 'failed',
            Payment.created_at < expired_date
        ).all()
        
        for payment in expired_payments:
            payment.status = 'expired'
        
        from app import db
        db.session.commit()
        
        return {
            'status': 'success',
            'expired_orders': len(expired_orders),
            'expired_payments': len(expired_payments)
        }
    except Exception as e:
        current_app.logger.error(f"清理过期数据失败: {e}")
        raise self.retry(countdown=3600, max_retries=2)


def generate_venue_usage_report(filters: Dict[str, Any]) -> Dict[str, Any]:
    """生成场馆使用报表"""
    # 实现场馆使用统计逻辑
    return {
        'total_orders': 100,
        'total_revenue': 50000,
        'popular_venues': ['篮球场', '羽毛球场', '网球场'],
        'peak_hours': ['18:00-20:00', '20:00-22:00']
    }


def generate_user_activity_report(filters: Dict[str, Any]) -> Dict[str, Any]:
    """生成用户活动报表"""
    # 实现用户活动统计逻辑
    return {
        'active_users': 500,
        'new_users': 50,
        'total_activities': 200,
        'user_retention_rate': 0.85
    }


def generate_revenue_report(filters: Dict[str, Any]) -> Dict[str, Any]:
    """生成收入报表"""
    # 实现收入统计逻辑
    return {
        'total_revenue': 100000,
        'monthly_growth': 0.15,
        'top_venues': ['篮球场', '羽毛球场'],
        'payment_methods': {'微信支付': 0.8, '支付宝': 0.2}
    }


def save_report_to_file(report_type: str, data: Dict[str, Any]) -> str:
    """保存报表到文件"""
    import json
    from datetime import datetime
    
    # 创建报表目录
    report_dir = os.path.join(os.getcwd(), 'reports')
    if not os.path.exists(report_dir):
        os.makedirs(report_dir)
    
    # 生成文件名
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    filename = f"{report_type}_{timestamp}.json"
    filepath = os.path.join(report_dir, filename)
    
    # 保存数据
    with open(filepath, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
    
    return filepath 